package com.shelpe.services.sinbad.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import org.apache.commons.lang3.math.NumberUtils;

import com.google.common.collect.Lists;
import com.shelpe.services.sinbad.controller.SearchCriteria;
import com.shelpe.services.sinbad.model.KeywordExample;
import com.shelpe.services.sinbad.model.RptKeywordExample;

public class CriteriaUtils {

	public static KeywordExample.Criteria toCriteria(KeywordExample.Criteria criteria, SearchCriteria sc){
		if("qscore".equals(sc.getKey())){
			float value = NumberUtils.toFloat(sc.getValue());
			if(sc.operation() == SearchCriteria.Operation.gte){
				criteria.andQscoreGreaterThanOrEqualTo(value);
			}else if(sc.operation() == SearchCriteria.Operation.gt){
				criteria.andQscoreGreaterThan(value);
			}else if(sc.operation() == SearchCriteria.Operation.lte){
				criteria.andQscoreLessThanOrEqualTo(value);
			}else if(sc.operation() == SearchCriteria.Operation.lt){
				criteria.andQscoreLessThan(value);
			}else{
				criteria.andQscoreEqualTo(value);
			}
		}
		
		if("wirelessQscore".equals(sc.getKey())){
			float value = NumberUtils.toFloat(sc.getValue());
			if(sc.operation() == SearchCriteria.Operation.gte){
				criteria.andWirelessQscoreGreaterThanOrEqualTo(value);
			}else if(sc.operation() == SearchCriteria.Operation.gt){
				criteria.andWirelessQscoreGreaterThan(value);
			}else if(sc.operation() == SearchCriteria.Operation.lte){
				criteria.andWirelessQscoreLessThanOrEqualTo(value);
			}else if(sc.operation() == SearchCriteria.Operation.lt){
				criteria.andWirelessQscoreLessThan(value);
			}else{
				criteria.andWirelessQscoreEqualTo(value);
			}
		}
		
		return criteria;
	}
	
	private static final List<String> FIELDS_NAME_WITH_FLOAT = Lists.newArrayList("cpc", "ctr", "cpm", "avgpos", "cvr", "roi", "favCountRate", "cartCountRate", "sale");
	private static final List<String> FIELDS_NAME_WITH_INTEGER = Lists.newArrayList("impressions", "click", "cost", "directPay", "indirectPay", "directPayCount", "indirectPayCount", "favShopCount", "favItemCount", "directCartTotal", "indirectCartTotal", "cartTotal", "payCount");
	
	public static RptKeywordExample.Criteria toCriteria(RptKeywordExample.Criteria criteria, SearchCriteria sc){
		Method m = CriteriaUtils.pickAndMethod(criteria, sc);
		if(m != null){
			try {
				if(FIELDS_NAME_WITH_FLOAT.contains(sc.getKey())){
					float value = NumberUtils.toFloat(sc.getValue());
					m.invoke(criteria, value);
				}else if(FIELDS_NAME_WITH_INTEGER.contains(sc.getKey())){
					int value = NumberUtils.toInt(sc.getValue());
					m.invoke(criteria, value);
				}
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}
		
		return criteria;
	}
	
	private static Method pickAndMethod(RptKeywordExample.Criteria criteria, SearchCriteria sc){
		String methodName = "and" + sc.getKey().substring(0, 1).toUpperCase() + sc.getKey().substring(1);
		if(sc.operation() == SearchCriteria.Operation.gte){
			methodName = methodName + "GreaterThanOrEqualTo";
		}else if(sc.operation() == SearchCriteria.Operation.gt){
			methodName = methodName + "GreaterThan";
		}else if(sc.operation() == SearchCriteria.Operation.lte){
			methodName = methodName + "LessThanOrEqualTo";
		}else if(sc.operation() == SearchCriteria.Operation.lt){
			methodName = methodName + "LessThan";
		}else{
			methodName = methodName + "EqualTo";
		}
		Method[] methods = criteria.getClass().getMethods();
		if(methods != null){
			for(Method m:methods){
				if(m.getName().equals(methodName)){
					return m;
				}
			}
		}
		return null;
	}
}
